using System;
using System.Collections.Generic;
using System.EnterpriseServices;
using System.Globalization;
using System.Reflection;

using COMAdmin;

namespace InvocationFramework.Adapters.EnterpriseServices
{
    /// <summary>
    /// </summary>
    /// <author>Rodolfo Finochietti 08/12/2006 20.45</author>
    internal static class COMPlusHelper
    {
        #region Private Vars
        
        private static Dictionary<string, Type> _components = new Dictionary<string, Type>( );

        #endregion

        #region Public Methods

        public static Dictionary<string, List<string>> GetComponents( )
        {
            Dictionary<string, List<string>> services = new Dictionary<string, List<string>>( );

            COMAdminCatalog admin = new COMAdminCatalog( );

            COMAdminCatalogCollection applications = ( COMAdminCatalogCollection )admin.GetCollection( "Applications" );
            applications.Populate( );

            foreach ( COMAdminCatalogObject application in applications )
            {
                ICatalogCollection components = ( ICatalogCollection )applications.GetCollection( "Components", application.Key );
                components.Populate( );

                foreach ( COMAdminCatalogObject component in components )
                {
                    string serviceName = component.Name.ToString( );

                    List<string> operations;
                    if ( services.ContainsKey( serviceName ) )
                    {
                        operations = services[ serviceName ];
                    }
                    else
                    {
                        operations = new List<string>( );
                        services.Add( serviceName, operations );
                    }

                    COMAdminCatalogCollection interfaces = ( COMAdminCatalogCollection )components.GetCollection( "InterfacesForComponent", component.Key );
                    interfaces.Populate( );

                    foreach ( COMAdminCatalogObject inter in interfaces )
                    {
                        COMAdminCatalogCollection methods = ( COMAdminCatalogCollection )interfaces.GetCollection( "MethodsForInterface", inter.Key );
                        methods.Populate( );

                        foreach ( COMAdminCatalogObject method in methods )
                        {
                            string operationName = method.Name.ToString( );
                            if ( !operations.Contains( operationName ) )
                                operations.Add( operationName );
                        }
                    }

                    interfaces = null;
                }

                components = null;
            }

            admin = null;
            applications = null;

            return services;
        }

        public static object InvokeMethod( string progId, string methodName, params object[] parameters )
        {
            Type componentType;
            if ( _components.ContainsKey( progId ) )
            {
                componentType = _components[ progId ];
            }
            else
            {
                componentType = Type.GetTypeFromProgID( progId );
                _components.Add( progId, componentType );
            }
            
            object ret = null;
            object component = Activator.CreateInstance( componentType );

            try
            {
                if ( componentType != null && component != null )
                    ret = componentType.InvokeMember( methodName, BindingFlags.Default | BindingFlags.InvokeMethod, null, component, parameters, CultureInfo.InvariantCulture );
            }
            finally
            {
                if ( component != null )
                {
                    ServicedComponent servComp = component as ServicedComponent;
                    if ( servComp != null )
                    {
                        servComp.Dispose( );
                        servComp = null;
                    }
                    component = null;
                }
            }

            return ret;
        }

        #endregion
    }
}